#!/usr/bin/env node
let writeStr = ""
let fs = require("fs")
let env = process.argv[2]
let isHardHat = process.argv[4]?process.argv[4]:true
let abi
if(isHardHat){
    abi = JSON.parse(fs.readFileSync(env).toString()).abi
}else{
    abi = JSON.parse(fs.readFileSync(env).toString())
}
let argName = process.argv[3]
let path = require("path")
let viewFunc = []
let payFunc = []
writeStr += `let Web3 = require("web3")\nlet config = require("./config/index.js")\nlet web3 = new Web3(new Web3.providers.HttpProvider(config.HTTP_PROVIDER))\nlet abi = require("${env}")${isHardHat?".abi":""}\nlet Contract = new web3.eth.Contract(abi,config.${argName})\n`
writeStr += `function addUser(){\n\tlet user = web3.eth.accounts.wallet.add(config.privateKey)\n\tweb3.eth.defaultAccount = user.address\n}\n`
abi.map((item,i)=>{
    if(item.type == "function"){
        if(item.stateMutability == "view"){
            viewFunc.push(item)
        }else{
            payFunc.push(item)
        }
    }
})
let funcName = ""
let funcNameGroup = []
let funcGroup = []
let attrGroup = {}
payFunc.map((item,i)=>{
    let funcStr = `async function ${item.name}(`
    let attrStr = `${item.name}(`
    funcName += item.name
    funcNameGroup.push(item.name)
    if(i!=payFunc.length-1){
        funcName += ","
    }
    attrGroup[item.name] = []
    item.inputs.map((attr,a)=>{
        funcStr += attr.name?attr.name:"attr"+(a+1)
        attrStr += attr.name?attr.name:"attr"+(a+1)
        attrGroup[item.name].push(attr.name?attr.name:"attr"+(a+1))
        if(a!=item.inputs.length-1){
            funcStr += ","
            attrStr += ","
        }
    })
    attrStr += ")"
    funcGroup.push(attrStr)
    funcStr += `){\n\tlet res = await new Promise((resolve,reject)=>{\n\t\taddUser()\n\t\tContract.methods.${attrStr}.estimateGas({from:web3.eth.defaultAccount}).then(gas=>{\n\t\t\tresolve(gas)\n\t\t}).catch(err=>{\n\t\t\treject(err)\n\t\t})\n\t})\n\treturn res\n}\n`
    writeStr += funcStr
})
writeStr += `module.exports = {web3,${funcName}}`
fs.writeFileSync(`${argName}.js`,writeStr)
let apiStr = `let web3Tools = require("./${argName}.js")\n`
funcGroup.map((item,i)=>{
    apiStr += `async function ${funcNameGroup[i]}(ctx){\n\tlet {\n\t`
    attrGroup[funcNameGroup[i]].map((attr,a)=>{
        apiStr += "\t"+attr
        if(a!=attrGroup[funcNameGroup[i]].length-1){
            apiStr += ",\n\t"
        }else{}
    })  
    apiStr += `\n\t} = ctx.request.body\n\tlet gas = await web3Tools.${item}.catch(err=>{\n\t\tconsole.log(err)\n\t\tctx.response.body = {code:500,msg:err.toString()}\n\t})\n\tif(!gas){\n\t\treturn ;\n\t}\n\tctx.response.body = {code:200,data:gas}\n}\n`
})
apiStr += `\nmodule.exports = {${funcName}}`
fs.writeFileSync(`api.js`,apiStr)
let appStr = `let koa = require("koa")\nlet api = require("./api.js")\nlet koaBody = require("koa-body")\nlet route = require("koa-route")\nlet app = new koa()\napp.use(koaBody())\napp.use(async(ctx,next)=>{\n\tctx.set('Access-Control-Allow-Origin', '*')\n\tctx.set('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , Token, Enctype')\n\tctx.set('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS')\n\tif (ctx.method == 'OPTIONS') {\n\t\tctx.body = 200;\n\t}else{\n\t\tawait next()\n\t}\n})\napp.use(route.get("/",async(ctx)=>{ctx.body = "服务器打开成功"}))\n`
funcNameGroup.map((item,i)=>{
    appStr += `app.use(route.post("/web3/${argName}/${item}",api.${item}))\n`
})
appStr += `app.listen(5000)\nconsole.log("Service is open,Port 5000")`
fs.writeFileSync("app.js",appStr)
let configStr
if(!fs.existsSync("./config/index.js")){
    if(!fs.existsSync("./config")){
        fs.mkdirSync("config")
    }
    configStr = `module.exports = {\n\tprivateKey:"",\n\tHTTP_PROVIDER:"https://bsc-dataseed.binance.org/",\n\t${argName}:""\n}`
}else{
    configStr = fs.readFileSync("./config/index.js").toString()
    configStr = configStr.split("\n}")[0] + `,\n\t${argName}:""\n}`
}
fs.writeFileSync("./config/index.js",configStr)